package com.simple.editor.ui;

import com.simple.editor.action.ActionManager;
import com.simple.editor.action.EditorUIAction;
import com.simple.editor.callback.UIEnableDisableCallback;
import com.simple.editor.vcs.VcsStatus;

import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;

/**
 * {@link ChangesPane} provides "Changes view" panel.
 * <p/>
 * Created with IntelliJ IDEA.
 * User: vlad
 * Date: 6/2/13
 * Time: 2:31 PM
 * To change this template use File | Settings | File Templates.
 */
public class ChangesPane extends JPanel {

    private final ActionManager actionManager;
    private final JTree fileTree;
    private final DefaultTreeModel treeModel;
    private final DefaultMutableTreeNode parent;
    private final JButton refreshBtn;
    private final JButton updateAllBtn;
    private final JButton commitAllBtn;

    public ChangesPane(final ActionManager actionManager) {

        this.actionManager = actionManager;
        setPreferredSize(new Dimension(400, 200));

        final DefaultMutableTreeNode root = new DefaultMutableTreeNode(".");
        parent = new DefaultMutableTreeNode("Default (No files)") {

        };
        root.add(parent);

        treeModel = new DefaultTreeModel(root);
        fileTree = new JTree(treeModel);
        fileTree.setExpandsSelectedPaths(true);
        fileTree.setRootVisible(false);
        fileTree.setCellRenderer(new ChangesPaneTreeCellRenderer());

        fileTree.addMouseListener(createMouseListener());

        //Enable tool tips.
        ToolTipManager.sharedInstance().registerComponent(fileTree);
        setLayout(new BorderLayout());

        final Box verticalBox = Box.createVerticalBox();
        verticalBox.setOpaque(false);

        refreshBtn = createButton("Refresh   ", "/refresh_btn.png", EditorUIAction.Type.REFRESH);
        verticalBox.add(refreshBtn);

        updateAllBtn = createButton("Update All", "/update_btn.png", EditorUIAction.Type.UPDATE);
        verticalBox.add(updateAllBtn);

        commitAllBtn = createButton("Commit All", "/commit_btn.png", EditorUIAction.Type.COMMIT);
        verticalBox.add(commitAllBtn);

        verticalBox.add(Box.createRigidArea(new Dimension(0, 10)));

        verticalBox.setBorder(BorderFactory.createEmptyBorder(2, 0, 0, 2));

        add(verticalBox, BorderLayout.WEST);
        final JScrollPane jScrollPane = new JScrollPane(fileTree,
                ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
                ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);

        jScrollPane.setBorder(BorderFactory.createEtchedBorder());
        add(jScrollPane, BorderLayout.CENTER);
    }

    public void removeFromChangesView(final String file) {
        final Enumeration enumeration = parent.children();
        while (enumeration.hasMoreElements()) {
            final ChangesNode node = (ChangesNode) enumeration.nextElement();
            if (node.getFile().getAbsolutePath().equals(file)) {
                parent.remove(node);
                parent.setUserObject(parent.getChildCount() == 0 ? "Default (No files)" : "Default (" + parent.getChildCount() + " file)");
                refreshTree();
                return;
            }
        }
    }

    public void refreshTree() {
        treeModel.reload();
        fileTree.revalidate();
        fileTree.expandRow(0);
    }

    public void addToChanges(final FileModel... files) {
        for (final FileModel file : files) {
            ChangesNode foundNode = null;
            final Enumeration enumeration = parent.children();
            while (enumeration.hasMoreElements()) {
                final ChangesNode node = (ChangesNode) enumeration.nextElement();
                if (node.getFile().getAbsolutePath().equals(file.getAbsolutePath())) {
                    foundNode = node;
                    break;
                }
            }
            if (foundNode == null) {
                parent.add(new ChangesNode(file));
            } else {
                foundNode.getFile().setStatus(file.getStatus());
                foundNode.getFile().setChanged(file.isChanged());
            }
        }

        // Update default parent node label
        parent.setUserObject("Default (" + parent.getChildCount() + " file)");

        refreshTree();
    }

    private MouseListener createMouseListener() {
        return new MouseAdapter() {

            @Override
            public void mouseReleased(final MouseEvent e) {
                final int selRow = fileTree.getRowForLocation(e.getX(), e.getY());
                if ((selRow != -1) && SwingUtilities.isRightMouseButton(e)) {

                    final Object component = fileTree.getLastSelectedPathComponent();
                    if (!(component instanceof ChangesNode)) {
                        return;
                    }

                    final int row = fileTree.getClosestRowForLocation(e.getX(), e.getY());
                    fileTree.setSelectionRow(row);
                    final JPopupMenu menu = new JPopupMenu();

                    final FileModel file = ((ChangesNode) fileTree.getLastSelectedPathComponent()).getFile();

                    if (file.getStatus() != VcsStatus.DELETED) {
                        menu.add(new JMenuItem(new AbstractAction("Open") {
                            @Override
                            public void actionPerformed(final ActionEvent event) {
                                actionManager.runAction(EditorUIAction.Type.OPEN, file);
                            }
                        }));
                        menu.add(new JMenuItem(new AbstractAction("Delete") {
                            @Override
                            public void actionPerformed(final ActionEvent event) {
                                actionManager.runAction(EditorUIAction.Type.DELETE, file);
                            }
                        }));
                    }

                    menu.add(new JMenuItem(new AbstractAction("Commit") {
                        @Override
                        public void actionPerformed(final ActionEvent event) {
                            actionManager.runAction(EditorUIAction.Type.COMMIT, file);
                        }
                    }));

                    menu.add(new JMenuItem(new AbstractAction("Update") {
                        @Override
                        public void actionPerformed(final ActionEvent event) {
                            actionManager.runAction(EditorUIAction.Type.UPDATE, file);
                        }
                    }));

                    menu.add(new JMenuItem(new AbstractAction("Revert") {
                        @Override
                        public void actionPerformed(final ActionEvent event) {
                            actionManager.runAction(EditorUIAction.Type.REVERT, file);
                        }
                    }));

                    menu.show(e.getComponent(), e.getX(), e.getY());
                }
            }
        };
    }

    private JButton createButton(final String label, final String icon, final EditorUIAction.Type actionType) {
        final JButton jButton = new JButton();
        jButton.setAction(new AbstractAction() {
            @Override
            public void actionPerformed(final ActionEvent e) {
                final List<FileModel> files = new ArrayList<FileModel>();
                final Enumeration enumeration = parent.children();
                while (enumeration.hasMoreElements()) {
                    final ChangesNode node = (ChangesNode) enumeration.nextElement();
                    files.add(node.getFile());
                }
                actionManager.runAction(new UIEnableDisableCallback(jButton), actionType, files);
            }
        });

        final Image image = new ImageIcon(TabbedEditorPane.class.getResource(icon)).
                getImage().getScaledInstance(50, 50, java.awt.Image.SCALE_SMOOTH);
        final Icon imageIcon = new ImageIcon(image);
        jButton.setIcon(imageIcon);
        jButton.setText(label);
        return jButton;
    }
}

